<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../style/journal.css" type="text/css" />
<style type="text/css"><!--
.googleadsense {
	margin: 2px;
	padding: 0px;
//--></style><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-65008-1";
urchinTracker();
</script><title>modperl 服务器的运行阶段和句柄</title>
</head>
<body>
<a href="index.html">Journal</a>(2005) | <a href="../blog/"><b>Blog</b></a>(2006) | <a href="http://www.fayland.org/cgi-bin/random_link.pl">RandomLink</a> | <a href="AboutFayland.html">WhoAmI</a> | <a href="LiveBookmark.html">LiveBookmark</a> | <a href="http://www.fayland.org/">HomePage</a>
<p><&lt;Previous: <a href="pod2cn.html">Perl 核心模块中文化</a>&nbsp;&nbsp;>>Next: <a href="modperl_PerlTransHandler.html">modperl 的 PerlTransHandler 应用</a></p>
<h1>modperl 服务器的运行阶段和句柄</h1>
<div class='content'>
<p>Category: <a href='mod_perl.html'>mod_perl</a> &nbsp; Keywords: <b>modperl http PerlHandler</b></p><img src='img/http_cycle_all.gif' alt='apache http cycle' /><p />上面这张图就是 <a href="http://perl.apache.org">modperl</a> 的服务器循环。本文大致是 <a href="http://perl.apache.org/docs/2.0/user/handlers/http.html">http://perl.apache.org/docs/2.0/user/handlers/http.html</a> 的翻译或阅读随记。<p />modperl 可以控制所有的 Apache http 的阶段，每一个阶段都对应一个句柄，就是我以前提过的 Perl*Handler:<br /><ol><br /><li>PerlPostReadRequestHandler (PerlInitHandler)</li><li>PerlTransHandler</li><li>PerlMapToStorageHandler</li><li>PerlHeaderParserHandler (PerlInitHandler)</li><li>PerlAccessHandler</li><li>PerlAuthenHandler</li><li>PerlAuthzHandler</li><li>PerlTypeHandler</li><li>PerlFixupHandler</li><li>PerlResponseHandler</li><li>PerlLogHandler</li><li>PerlCleanupHandler</li></ol><p />图上右边 9 个阶段和下面的 Response 阶段都可能返回终止信号，终止后不继续运行下面的阶段而是跳转到 Log 阶段，而后 Cleanup, 最后等待下一次连接。<p />所有的 12 个阶段都有下面的结构：<br /><pre>  package MyApache2::MyHandlerName;<br />  <br />  # load modules that are going to be used<br />  use ...;<br />  <br />  # compile (or import) constants<br />  use Apache2::Const -compile => qw(OK);<br />  <br />  sub handler {<br />      my $r = shift;<br />      <br />      # handler code comes here<br />      <br />      return Apache2::Const::OK; # or another status constant<br />  }<br />  1;</pre>其中 $r 还是 <a href="http://search.cpan.org/perldoc?Apache2::RequestRec">Apache2::RequestRec</a> 的一个实例。如果你需要获得类的名字，则需要这么写：<br /><pre>sub handler : method {<br />    my($class, $r) = @_;</pre>这种写法与 modperl 1.x 中的 sub handler($$) { 大致上是一致的。<p />PerlResponseHandler 是由以前的 PerlHandler 更名而来的，而且它现在包括了 Filters.<h2>Handler Type</h2>在介绍每个阶段都是干什么的之前，我想先要弄清楚每个阶段的一些行为，或者称之为类型。<br />按我的暂时的理解，这种类型的意义在于处理一个阶段的多个句柄（为避免混淆，一般称它们为 hook）时，比如<br /><pre>Perl*Handler Apache::One Apache::Two Apache::Three</pre>这里阶段是 *, 句柄是 Perl*Handler, 而 Apache::One Apache::Two 等则称为 hooks.<br /><ul>我们总共有三个类型<br /><li>VOID: 这种类型的句柄，不管 Apache::One Apache::Two 等返回什么，都按顺序执行下去<br /><li>RUN_FIRST: 当遇到第一个 hook 不是返回 Apache2::Const::DECLINED 时停止。比如 Apache::One 返回 Apache2::Const::DECLINED, 就继续执行 Apache::Two, 直到某个 hook 不返回 Apache2::Const::DECLINED. 比如 Apache::Two 返回 Apache2::Const::OK 时就结束这个阶段跳转到下一个阶段，而不是继续执行 Apache::Three<br /><li>RUN_ALL: 直到返回值不是 Apache2::Const::OK 或 Apache2::Const::DECLINED 时才结束这个阶段，否则按顺序执行多个 hooks.<br /></ul>下面是所有阶段的类型：<br /><pre>    Directive                   Type<br />  --------------------------------------<br />  PerlOpenLogsHandler          RUN_ALL<br />  PerlPostConfigHandler        RUN_ALL<br />  PerlChildInitHandler         VOID<br />  PerlChildExitHandler         VOID<br />  <br />  PerlPreConnectionHandler     RUN_ALL<br />  PerlProcessConnectionHandler RUN_FIRST<br />  <br />  PerlPostReadRequestHandler   RUN_ALL<br />  PerlTransHandler             RUN_FIRST<br />  PerlMapToStorageHandler      RUN_FIRST<br />  PerlInitHandler              RUN_ALL<br />  PerlHeaderParserHandler      RUN_ALL<br />  PerlAccessHandler            RUN_ALL<br />  PerlAuthenHandler            RUN_FIRST<br />  PerlAuthzHandler             RUN_FIRST<br />  PerlTypeHandler              RUN_FIRST<br />  PerlFixupHandler             RUN_ALL<br />  PerlResponseHandler          RUN_FIRST<br />  PerlLogHandler               RUN_ALL<br />  PerlCleanupHandler           RUN_ALL<br />  <br />  PerlInputFilterHandler       VOID<br />  PerlOutputFilterHandler      VOID</pre><h2>Handler Introduction</h2>下面简单的介绍下各个阶段，而各阶段的运用代码以后我想我会都试验一下的。<h4>PerlPostReadRequestHandler</h4>这个阶段在请求被接受和 HTTP header 被解析后立即运行。这个阶段一般用于处理那些每个请求都只运行一次的事情。<br />比如 <a href="http://search.cpan.org/perldoc?Apache2::Reload">Apache2::Reload</a> 一般就在这个阶段被执行。<h4>PerlTransHandler</h4>这个阶段一般对请求的 URI 进行操作处理。<br />如果没有自定义的句柄，则服务器的 translate 标准规则（如 Alias 指示符和 mod_rewrite 等）则被使用。<br />如果使用了字定义的句柄，它将修改默认的 translate 机制或覆盖它们。<br />它还可以为 PerlMapToStorageHandler 注册一些新的句柄。<h4>PerlMapToStorageHandler</h4>这个阶段用于将一个 URI 对应到一个真实的文件上。<h4>PerlHeaderParserHandler</h4>此阶段是请求/Request 对应到一个 <Location （或类似的东西）时所发生的第一个阶段。<br />在此阶段它能检查请求的 header 并对其进行操作。<br />这个阶段与最初的 PerlPostReadRequestHandler 阶段类似，唯一不同的就是它要对应到 <Lacation 之后。<h4>PerlAccessHandler</h4>这是 AAA: Authentication and Authorization, and Access control 的第一个阶段。<br />这个阶段能控制访问者的 IP, 访问的时间段其他与用户有关的限制。<h4>PerlAuthenHandler</h4>该阶段当访问密码保护的文件或文件夹时发生。当然这些密码保护的文件或文件夹需要类如 AuthName, AuthType 这样的东西。（想想 .htaccess ）<br />当验证通过时返回 Apache2::Const::OK，授权失败则是 Apache2::Const::HTTP_UNAUTHORIZED。这就是通常的 403.<h4>PerlAuthzHandler</h4>这个阶段和 PerlAuthenHandler 差不多的捆绑在一起的。我目前实在没什么心情继续看完这个阶段。以后再讨论。<h4>PerlTypeHandler</h4>这个阶段用于设置响应/Response 的 MIME type (Content-type) 和类如文档语言等之类的东西。<h4>PerlFixupHandler</h4>这个阶段是 PerlResponseHandler 前的最后一个阶段。一般用于处理一些响应前要做但可能还没做的事。<br />比如在此阶段 mod_env 导入了由 SetEnv 和 PassEnv 所设置的环境变量。<h4>PerlResponseHandler</h4>毫无疑问这是最最重要的阶段。它用于生成响应的内容（就是返回浏览器的内容）。<h4>PerlLogHandler</h4>这个阶段无论如果都是会被进行的，原因在文章的最初解释过了。用于纪录一些信息。<h4>PerlCleanupHandler</h4>这个是 modperl 所独有的阶段。用于处理清尾工作。比如移除临时文件等。<h2>Have fun!</h2>如果有什么错误之处，请务必务必发 email 给我： fayland[AT]gmail.com<br />Thanks.</div>
<p><&lt;Previous: <a href="pod2cn.html">Perl 核心模块中文化</a>&nbsp;&nbsp;>>Next: <a href="modperl_PerlTransHandler.html">modperl 的 PerlTransHandler 应用</a></p>
<p><strong>Options:</strong> <a href='http://del.icio.us/post?title=modperl%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E8%BF%90%E8%A1%8C%E9%98%B6%E6%AE%B5%E5%92%8C%E5%8F%A5%E6%9F%84&url=http://www.fayland.org/journal/modperl_http_cycle.html'>+Del.icio.us</a></p>
<strong>Related items</strong>
<ul><li><a href='modperl_helloworld.html'>modperl Apache2::HelloWorld</a> < <span class='digit'>2005-11-16 23:24:07</span> ></li><li><a href='modperl_PerlTransHandler.html'>modperl 的 PerlTransHandler 应用</a> < <span class='digit'>2005-11-23 22:24:02</span> ></li><li><a href='modperl_PerlAuthenHandler.html'>modperl 的用户验证</a> < <span class='digit'>2005-11-26 00:08:37</span> ></li><li><a href='modperl_Filter_part1.html'>modperl Filter Part1</a> < <span class='digit'>2005-12-18 14:47:29</span> ></li></ul>
Created on <span class="digit">2005-11-22 15:33:08</span>, Last modified on <span class="digit">2005-11-25 11:43:09</span><br />
Copyright 2004-2005 All Rights Reserved. Powered by <a href="Eplanet.html">Eplanet</a> && <a href='http://catalyst.perl.org'>Catalyst</a> 5.62.
</body>
</html>